﻿using BaseMsg;
using K.Client;
using ProtoBuf;
using System;
using System.IO;
using UnityEngine;

public class GameClient : Singleton<GameClient>, IZUpdate
{
    private delegate void MsgModuleDispatcher(Msg msg);
    private MsgModuleDispatcher[] moduleDispatchers;

    public LuaNetMgr gateNetMgr;        //网关网络管理器
    private static float mFlyTime;      //经历的时长
    private bool mConnected;            //是否连接到网关
    public bool mSendHeart;             //是否发送心跳 -- 用于ios检测

    public float mHeartIntervalTime;    //心跳经历时间 -- 用于ios检测
    private float mIntervalTime;        //间隔时间
    private int mReconnectCount;        //重连次数
    
    public void AddReconnectNum()
    {
        mReconnectCount++;
    }

    public GameClient()
    {
        mConnected = false;
        mSendHeart = false;

        mFlyTime = 0f;
        mReconnectCount = 0;
        mHeartIntervalTime = 0;

        LuaMsg.Init(LuaMsgFactory.SerializeHead, LuaMsgFactory.DeserializeHead);
        moduleDispatchers = new MsgModuleDispatcher[(int)EModuleType.MODULE_END];
        moduleDispatchers[(int)EModuleType.MODULE_PF] = Activator.CreateInstance<PfModule>().OnMsg;
        LuaMgr.GetSingleton().LoadLuaMsg();
    }

    public bool ConnectGate()
    {
        DBSystemMgr.GetSingleton();
        WebClient.GetSingleton().CloseConnectWebSvr();
        
        string gateHost = ""; int gatePort = 31000;
        ZMgr.WaitServerMgr.StartWait("开始连接");
        gateNetMgr = new LuaNetMgr(false); 

        try
        {
            gateNetMgr.Connect(gateHost, gatePort);
        }
        catch (Exception e)
        {
            EDebug.Log(string.Format("服务器连接失败：\n{0}", e.ToString()));
            OnDisconnect(); return false;
        }
        ZMgr.WaitServerMgr.EndWait("连接成功");
        gateNetMgr.MgrName = "gateNetMgr";

        mSendHeart = false;
        mConnected = true;
        Time.timeScale = 1;
        mReconnectCount = 0;
        return true;
    }

    public void ZUpdate()
    {
        if (mConnected)
        {
            try
            {
                gateNetMgr.RecvMsg(2000, OnGateMsg);
            }
            catch (IOException e)
            {
                EDebug.Log(string.Format("服务器连接断开：\n{0}", e.ToString()));
                OnDisconnect(); return;
            }
            if (CanDisconnect())
            {
                EDebug.Log(string.Format("服务器连接断开：\n{0}", "客户端发送消息，10s内没有响应"));
                OnDisconnect(); return;
            }
            // 发送心跳
            SendHeartBeat();
        }
    }

    private bool CanDisconnect()
    {
        if (mSendHeart)
        {
            mHeartIntervalTime += Time.deltaTime;
            // 说明 10s内没有回应
            if (mHeartIntervalTime >= 10)
            {
                mSendHeart = false;
                mHeartIntervalTime = 0;
                return true;
            }
        }
        return false;
    }

    private void SendHeartBeat()
    {
        mFlyTime += Time.deltaTime;
        // 加载或者播放镜头动画不发送心跳
        if (ZMgr.SceneMgr.isloading)
        {
            mFlyTime = 0f;
            return;
        }

        if (mFlyTime >= mIntervalTime)
        {
            mFlyTime = 0f;
        }
    }

    private int OnGateMsg(LuaMsg luaMsg)
    {
        // 心跳消息回复，不结束
        LuaMgr.GetSingleton().RecvLuaMsg(luaMsg);
        Msg msg = LuaMsgFactory.LuaMsgToMsg(luaMsg);
        if (msg == null) { return -1; }

        int moduleType = (luaMsg.id & 0x0FF000) >> 12;
        // 如果是各模块的消息,那么让模块自己处理
        if (moduleType < 0 || moduleType >= (int)EModuleType.MODULE_END)
        {
            return -1;
        }
        
        MsgModuleDispatcher dispatcher = moduleDispatchers[moduleType];
        if (dispatcher != null)
        {
            dispatcher(msg);
        }
        return 0;
    }
    
    public void OnDisconnect()
    {
        mReconnectCount++;
        // 清空新手引导信息
        ZMgr.GuideMgr.StopGuide();
        Time.timeScale = 0; // 暂停副本
        BehaviourUtil.StopAllCoroutines(); // 停止所有协成

        if (mReconnectCount == 1)
        {
            //清理资源之前，停止加载界面
            ZMgr.UIMgr.SetOpeningStatus(false);
            // 关闭loadingwait界面，防止卡到重连界面上
            ZMgr.LoadWaitMgr.CloseWaitLoading();
            // 解除屏幕锁定
            UIInputMgr.GetSingleton().ClearLockUIInput();
            // 清理所有相关界面
            ZMgr.UIMgr.ClearResource();
        }
        ReconnectMgr.GetSingleton().Open();
        mConnected = false;
        ZMgr.WaitServerMgr.EndWait("断开连接");
    }
    
    /// <summary>
    /// 断线重连
    /// </summary>
    public void NewConnectGate()
    {
        if (mReconnectCount == 1) // 防止在界面出现的同时有新的界面打开,车库中换部件，能出现这种情况
        {
            ZMgr.UIMgr.ClearResource();
            ZEventCenter.DispatchEvent(new ZEvent(ConstData.SCENE_LOAD_START));
        }
        PlayerData.GetSingleton().ReconnectInitData();
        // 清空新手引导信息
        ZMgr.GuideMgr.GuideVO = null;
        
        ReconnectMgr.GetSingleton().Close();
        LoadingMgr.GetSingleton().Close();
        AllUpdate.PlatFormMgr.LogOut();
    }

    public void SendToGate(LuaMsg msg, bool bLockScreen)
    {
        if (mConnected)
        {
            if (bLockScreen)
            {
                ZMgr.WaitServerMgr.StartWait(msg.id);
            }
            try
            {
                gateNetMgr.SendMsg(msg);

            }
            catch (Exception e)
            {
                OnDisconnect();
                return;
            }
        }
    }

    public void SendToGate(Msg msg)
    {
        LuaMsg luaMsg = new LuaMsg();
        SendToGate(luaMsg, false);
    }
    
    public void SendToGate(int id, IExtensible body)
    {
        SendToGate(MsgFactory.Create(id, body));
    }

    public void SendToGate(int id, IExtensible body, bool bLockScreen)
    {
        SendToGate(LuaMsgFactory.Create(id, body), bLockScreen);
    }
}